// Appliction implementation for FLTK
// Copyright 2005 (C) Ralph Thomas

#include <toolkit/application.h>
#include <util/resources.h>
#include <fltk/run.h>
#include <fltk/Symbol.h>
#include <fltk/SharedImage.h>
#include <vector>
#include <algorithm>

namespace bfs = boost::filesystem;

namespace toolkit {
	class applicationImpl : public application {
		typedef std::vector<idle*> idleList;
		idleList _idlers;
		bool _quit;
		//
		// void callIdlers()
		//
		/// This function will call all of the idle functions.
		//
		void callIdlers() {
			//
			// Make a safe copy that won't get modified by idle
			// handlers.
			//
			idleList safe( _idlers );
			idleList::iterator i = safe.begin();
			while( i != safe.end() ) {
				//
				// If we can find *i inside _idlers then it's ok
				// to call it.
				//
				if( std::find( _idlers.begin(), _idlers.end(), *i ) != _idlers.end() )
					(*i)->process();
				i++;
			}
		}
	  public:
		applicationImpl() : _quit( false ) {}
		virtual ~applicationImpl() {}
		//
		// from toolkit/application.h
		//
		virtual initReturn init() {
			bfs::path resource( util::getResourcePath() );
			std::string star_path( bfs::path( resource / "star16.png" ).native_file_string() );
			std::string rotate_cw_path( bfs::path( resource / "rotate_cw.png" ).native_file_string() );
			std::string rotate_ccw_path( bfs::path( resource / "rotate_ccw.png" ).native_file_string() );
			//
			// Load extra icons and things into FLTK.
			//
			fltk::SharedImage* star(
				fltk::pngImage::get( star_path.c_str() ) );
			if( star ) ((fltk::Symbol*)star)->name( "star" );
			fltk::SharedImage* rotate_cw(
				fltk::pngImage::get( rotate_cw_path.c_str() ) );
			if( rotate_cw ) ((fltk::Symbol*)rotate_cw)->name( "rotate_cw" );
			fltk::SharedImage* rotate_ccw(
				fltk::pngImage::get( rotate_ccw_path.c_str() ) );
			if( rotate_ccw ) ((fltk::Symbol*)rotate_ccw)->name( "rotate_ccw" );
			//
			// The star has to live as long as the application does,
			// so it's not too bad if we leak it.
			//
			return kOk;
		}
		virtual void run() {
			_quit = false;
			while( !_quit ) {
				fltk::wait( 1000 );
				callIdlers();
			}
		}
		virtual void quit() {
			_quit = true;
		}
		virtual void addIdle( idle* idleHandler, unsigned int freq ) {
			_idlers.push_back( idleHandler );
		}
		virtual void removeIdle( idle* idleHandler ) {
			idleList::iterator i = std::find( _idlers.begin(),
				_idlers.end(), idleHandler );
			if( i != _idlers.end() ) _idlers.erase( i );
		}
		virtual void doIdle() { callIdlers(); }
	};
	application& application::getInstance() {
		static applicationImpl app;
		return app;
	}
}

			
